#include "stdafx.h"
#include "wf_polylineequidistant.h"
#include "pf_polyline.h"
#include "pf_snapper.h"
#include "pf_information.h"

WF_PolylineEquidistant::WF_PolylineEquidistant(PF_Container& container,
		PF_GraphicView& graphicView)
		:PF_PreviewActionInterface("Create Equidistant Polylines",
						   container, graphicView) {
	dist = 1.0;
}


QAction* WF_PolylineEquidistant::createGUIAction(LX_Define::ActionType /*type*/, QObject* /*parent*/) {
	QAction* action = new QAction(tr("Create &Equidistant Polylines"), NULL);
	action->setShortcut(QKeySequence());
	action->setStatusTip(tr("Create Equidistant Polylines"));
	return action;
}

void WF_PolylineEquidistant::init(int status) {
	PF_ActionInterface::init(status);
	originalEntity = NULL;
	targetPoint = PF_Vector(false);
	bRightSide = false;
}

bool WF_PolylineEquidistant::makeContour() {
	if (container==NULL) {
		PF_DEBUG->print("PF_ActionPolylineEquidistant::makeContour: no valid container",
						PF_Debug::D_WARNING);
		return false;
	}

	PF_Vector offset(false);
        QList<PF_Entity*> addList;

	if (document!=NULL) {
		document->startUndoCycle();
	}
	double neg = 1.0;
	if(bRightSide)
		neg = -1.0;
	// Create new entites
	PF_Line line1(NULL, PF_LineAttribute(PF_Vector(true), PF_Vector(true)));
	PF_Line line2(NULL, PF_LineAttribute(PF_Vector(true), PF_Vector(true)));
	for (int num=1;
			num<=number || (number==0 && num<=1);
			num++) {
		PF_Polyline* newPolyline = new PF_Polyline(container);
		newPolyline->setClosed(((PF_Polyline*)originalEntity)->isClosed());
//		newPolyline->setSelected((PF_Polyline*)originalEntity)->isSelected());
		newPolyline->setLayer(((PF_Polyline*)originalEntity)->getLayer());
		newPolyline->setPen(((PF_Polyline*)originalEntity)->getPen());

		bool first = true;
		PF_Entity* lastEntity = ((PF_Polyline*)originalEntity)->lastEntity();
		for (PF_Entity* en=((PF_Polyline*)originalEntity)->firstEntity(); en!=NULL; en=((PF_Polyline*)originalEntity)->nextEntity()) {
			double bulge = 0.0;
			if (en->rtti()==LX_Define::EntityArc) {
				double r0 = ((PF_Arc*)en)->getRadius();
				double r = r0 - dist*neg;
				if(r < 0)
					break;
				((PF_Arc*)en)->setRadius(r);
				bulge = ((PF_Arc*)en)->getBulge();
				((PF_Arc*)en)->setRadius(r0);
			} else {
				bulge = 0.0;
			}
			PF_Vector v1 = ((PF_AtomicEntity*)en)->getStartpoint();
			PF_Vector v2 = ((PF_AtomicEntity*)en)->getEndpoint();
			offset.set(dist * cos(v1.angleTo(v2)+M_PI*0.5*neg), dist * sin(v1.angleTo(v2)+M_PI*0.5*neg));
			v1.move(offset*num);
			v2.move(offset*num);
			if (first) {
				line1.setStartpoint(v1);
				line1.setEndpoint(v2);
				if(newPolyline->isClosed()){
					PF_Vector v01 = ((PF_AtomicEntity*)lastEntity)->getStartpoint();
					PF_Vector v02 = ((PF_AtomicEntity*)en)->getStartpoint();
					offset.set(dist * cos(v01.angleTo(v02)+M_PI*0.5*neg), dist * sin(v01.angleTo(v02)+M_PI*0.5*neg));
					v01.move(offset*num);
					v02.move(offset*num);
					line2.setStartpoint(v01);
					line2.setEndpoint(v02);
					PF_VectorSolutions vsol = PF_Information::getIntersection(&line1, &line2, false);
					v1 = vsol.get(0);
				}
				newPolyline->setStartpoint(v1);
				newPolyline->addVertex(v1, bulge);
				first = false;
			}else{
				line2.setStartpoint(v1);
				line2.setEndpoint(v2);
				PF_VectorSolutions vsol = PF_Information::getIntersection(&line1, &line2, false);
				PF_Vector v = vsol.get(0);
				newPolyline->addVertex(v, bulge);
				newPolyline->setEndpoint(v);
				line1.setStartpoint(v1);
				line1.setEndpoint(v2);
				if (en==lastEntity/* && newPolyline->isClosed()==false*/){
					newPolyline->addVertex(v2, bulge);
				}
			}
		}
		double bulge = lastEntity->rtti() == LX_Define::EntityArc? ((PF_Arc*)lastEntity)->getBulge():0.0;
//		newPolyline->setNextBulge(bulge);
		newPolyline->endPolyline();
		container->addEntity(newPolyline);
		document->addUndoable(newPolyline);
	}
	if (document!=NULL) {
		document->endUndoCycle();
	}

	if (graphicView!=NULL) {
		graphicView->redraw();
	}

	return true;
}

void WF_PolylineEquidistant::trigger() {

	PF_DEBUG->print("PF_ActionPolylineEquidistant::trigger()");

	if (originalEntity!=NULL && targetPoint.valid ) {

		originalEntity->setHighlighted(false);
		graphicView->drawEntity(originalEntity);

		makeContour();

		originalEntity = NULL;
		targetPoint = PF_Vector(false);
		bRightSide = false;
		setStatus(ChooseEntity);

		PF_DIALOGFACTORY->updateSelectionWidget(container->countSelected());
	}
////////////////////////////////////////2006/06/15
		graphicView->redraw();
////////////////////////////////////////
}



void WF_PolylineEquidistant::mouseMoveEvent(PF_MouseEvent* e) {
	PF_DEBUG->print("PF_ActionPolylineEquidistant::mouseMoveEvent begin");

	switch (getStatus()) {
	case ChooseEntity:
		snapPoint(e);
		break;
	default:
		break;
	}

	PF_DEBUG->print("PF_ActionPolylineEquidistant::mouseMoveEvent end");
}



void WF_PolylineEquidistant::mouseReleaseEvent(PF_MouseEvent* e) {
        if (e->button()==Qt::LeftButton) {
		switch (getStatus()) {
		case ChooseEntity:
			originalEntity = catchEntity(e);
			if (originalEntity==NULL) {
				PF_DIALOGFACTORY->commandMessage(tr("No Entity found."));
			} else if (originalEntity->rtti()!=LX_Define::EntityPolyline) {

				PF_DIALOGFACTORY->commandMessage(
					tr("Entity must be a polyline."));
			} else {
				targetPoint = snapPoint(e);
				originalEntity->setHighlighted(true);
				graphicView->drawEntity(originalEntity);
				double d = graphicView->toGraphDX(snapRange)*0.9;
				PF_Entity* Segment =  ((PF_Polyline*)originalEntity)->getNearestEntity( targetPoint, &d, LX_Define::ResolveNone);
				double ang = ((PF_Line*)Segment)->getAngle1();
				double ang1 = ((PF_Line*)Segment)->getStartpoint().angleTo(PF_Vector(targetPoint));
				if( ang > ang1 || ang + M_PI < ang1 )
					bRightSide = true;
////////////////////////////////////////2006/06/15
		graphicView->redraw();
////////////////////////////////////////
				trigger();
			}
			break;
		default:
			break;
		}
        } else if (e->button()==Qt::RightButton) {
		deleteSnapper();
		if (originalEntity!=NULL) {
			originalEntity->setHighlighted(false);
			graphicView->drawEntity(originalEntity);
////////////////////////////////////////2006/06/15
		graphicView->redraw();
////////////////////////////////////////
		}
		init(getStatus()-1);
	}
}

void WF_PolylineEquidistant::showOptions() {
	PF_ActionInterface::showOptions();

	PF_DIALOGFACTORY->requestOptions(this, true);
}



void WF_PolylineEquidistant::hideOptions() {
	PF_ActionInterface::hideOptions();

	PF_DIALOGFACTORY->requestOptions(this, false);
}

void WF_PolylineEquidistant::updateMouseCursor() {
	graphicView->setMouseCursor(LX_Define::CadCursor);
}

void WF_PolylineEquidistant::updateMouseButtonHints() {
	switch (getStatus()) {
	case ChooseEntity:
		PF_DIALOGFACTORY->updateMouseWidget(tr("Choose the original polyline"),
											tr("Cancel"));
		break;
	default:
		PF_DIALOGFACTORY->updateMouseWidget("", "");
		break;
	}
}

void WF_PolylineEquidistant::updateToolBar() {
	switch (getStatus()) {
	case ChooseEntity:
		PF_DIALOGFACTORY->requestToolBar(LX_Define::ToolBarSnap);
		break;
	default:
		PF_DIALOGFACTORY->requestToolBar(LX_Define::ToolBarPolylines);
		break;
	}
}
// EOF
